package model.algorithms.a_star;

import java.util.ArrayList;

import model.algorithms.IAction;
import model.algorithms.IDistance;
import model.algorithms.IDomain;
import model.algorithms.State;
import model.algorithms.bfs.BFS;

public class AStar extends BFS {
	
	private IDistance g;
	
	public AStar(IDomain domain, IDistance g, IDistance h) {
		super(domain, h);
		this.g = g;
	}

	public ArrayList<IAction> search(State start, State goal) {
		start.setG(0);
		addToOpenList(start);
		start.setF(g.getDistance(start, start) + h.getDistance(start, goal));

		while (!isEmptyOpenList()) {
			State q = pollFromOpenList();
			
			if (q.equals(goal)) {
				return reconstructPath(start, q);
			}

			addToCloseList(q);

			for (IAction action : domain.getActions(q)) {
				State qTag = action.doAction(q);
				qTag.setG(g.getDistance(start, qTag));

				double tentative_g_score = q.getG() + domain.distance(q, qTag);

				if (containsInCloseList(qTag) && tentative_g_score >= qTag.getG()) {
					continue;
				}

				if (!containsInOpenList(qTag) || tentative_g_score < qTag.getG()) {
					qTag.setCameFromState(q);
					qTag.setCameFromAction(action);
					
					qTag.setG(tentative_g_score);
					qTag.setF(qTag.getG() + h.getDistance(qTag, goal));
						}	
					if (!containsInOpenList(qTag)) {
						addToOpenList(qTag);
					}
				}
			}
		
		return new ArrayList<IAction>();
	}

//	private ArrayList<IAction> reconstructPath(State goal, State start) {
//		if (goal.getCameFromState() != null) {
//			ArrayList<IAction> path = reconstructPath(goal.getCameFromState(),start);
//			path.add(goal.getCameFromAction());
//			return path;
//		}	
//		return new ArrayList<IAction>();
//	}
	
	private ArrayList<IAction> reconstructPath(State start, State goal) {
	if (goal.getCameFromState() != null) {
		ArrayList<IAction> path = reconstructPath(start ,goal.getCameFromState());
		path.add(goal.getCameFromAction());
		return path;
	}	
	return new ArrayList<IAction>();
}
}
